import java.awt.Graphics2D;
import java.awt.font.FontRenderContext;
import java.awt.font.TextLayout;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.Serializable;
import java.util.HashSet;
import java.util.Set;

public abstract class Named implements Serializable  {
	protected String name = "";
	protected Rectangle2D labelRectangle = new Rectangle2D.Double();
	protected Configuration config = Configuration.getDefaultConfiguration();
	protected Point2D labelPoint = new Point2D.Double();
    protected boolean selected, hovered, held, indicated, highlighted, relationSelected;
	
	public String getName() {
		return name;
	}

	public void setNameUnsafe(String name) {
		this.name = name;
	}

	public void setName(String name) {
		if (!name.equals(this.name)) {
			this.name = generateName(name);
		}
	}

	public void setName() {
		this.name = generateName("");
	}

	public abstract String generateName(String preferredName);

	public Point2D getLabelPoint() {
		return new Point2D.Double(labelRectangle.getX(), labelRectangle.getY());
	}

	public boolean isCloseLabel(Point2D point) {
		return labelRectangle.contains(point);
	}

	protected void calculateLabelPoint(double w, double h) {
	}

	public void paintLabel(Graphics2D g) {
		paintLabel(g, name);
	}

	public void paintLabel(Graphics2D g, String name) {
		if (name.isEmpty()) {
			return;
		}
		FontRenderContext frc = g.getFontRenderContext();
		TextLayout tl = new TextLayout(name, config.labelFont, frc);
		Rectangle2D bounds = tl.getBounds();
		calculateLabelPoint(bounds.getWidth(), bounds.getHeight());
		labelRectangle.setRect(labelPoint.getX(), labelPoint.getY(), bounds
				.getWidth(), bounds.getHeight());
		g.setPaint(config.backgroundColor);
		g.fill(labelRectangle);
		g.setPaint(config.labelColor);
		tl.draw(g, (float) labelPoint.getX(),
				(float) (labelPoint.getY() + bounds.getHeight()));
	}

	protected Set<Named> getNamePool() {
		return new HashSet<Named>();
	}

	/**
	 * @param name
	 * @return the smallest index that divides name in two, where the second
	 *         part consists only of digits.
	 */
	public static int digitSeparation(String name) {
		for (int i = name.length() - 1; i >= 0; i--) {
			int num = name.charAt(i) - '0';
			if (num < 0 || num > 9) {
				return i + 1;
			}
		}
		return 0;
	}
}
